// loader
import {
  getFullSettings,
  VimPartialSettings,
  VimSettings
} from '../vimSettings'

import { Vim } from '../vim'

import { ElementMapping } from '../elementMapping'
import {
  BFast,
  RemoteBuffer,
  requestHeader,
  IProgressLogs,
  VimDocument,
  G3d,
  VimHeader,
} from 'vim-format'
import { DefaultLog } from 'vim-format/dist/logging'


/**
* Asynchronously opens a vim object from a given source with the provided settings.
* @param {string | ArrayBuffer} source - The source of the vim object, either a string or an ArrayBuffer.
* @param {VimPartialSettings} settings - The settings to configure the behavior of the vim object.
* @param {(p: IProgressLogs) => void} [onProgress] - Optional callback function to track progress logs.
* @returns {Promise<Vim>} A Promise that resolves when the vim object is successfully opened.
*/
export async function open(
  source: string | ArrayBuffer,
  settings: VimPartialSettings,
  onProgress?: (p: IProgressLogs) => void
) {
  const fullSettings = getFullSettings(settings)
  const type = await requestFileType(source)
  if (type === 'vim') {
    return loadFromVim(source, fullSettings, onProgress)
  }


  throw new Error('无法确定加载类型')
}



async function requestFileType(vimPath: string | ArrayBuffer) {
  if (typeof vimPath === 'string') {
    if (vimPath.endsWith('.vim')) return 'vim'
    if (vimPath.endsWith('.vimx')) return 'vimx'
  }

  const bfast = new BFast(vimPath)
  const header = await requestHeader(bfast)

  if (header.vim) return 'vim'
  if (header.vimx) return 'vimx'

  throw new Error('无法从文件确定类型')
}

/**
 * Loads a Vim file from source
 */
async function loadFromVim(
  source: string | ArrayBuffer,
  settings: VimSettings,
  onProgress?: (p: IProgressLogs) => void
) {
  const fullSettings = getFullSettings(settings)
  const bfast = new BFast(source)
  if (bfast.source instanceof RemoteBuffer) {
    if (onProgress) { bfast.source.onProgress = onProgress }
    if (settings.verboseHttp) {
      bfast.source.logs = new DefaultLog()
    }
  }

  // Fetch g3d data
  const geometry = await bfast.getBfast('geometry')
  const g3d = await G3d.createFromBfast(geometry)
  
  

  // Create legacy mapping
  const doc = await VimDocument.createFromBfast(bfast, true)
  const mapping = await ElementMapping.fromG3d(g3d, doc)
  const header = await requestHeader(bfast)

  const vim = new Vim(
    header,
    g3d,
    fullSettings,
    mapping,
    doc,
  )

  return vim
}
